package com.ytjj.qmyx.admin.service.data.impl;

import com.ytjj.common.constants.StatisticsConstants;
import com.ytjj.common.service.RedisService;
import com.ytjj.qmyx.admin.constants.data.MongoCollectionNameConstants;
import com.ytjj.common.constants.PlatformConstant;
import com.ytjj.qmyx.admin.dao.AnalysisDao;
import com.ytjj.qmyx.admin.dao.data.DataStatisticDao;
import com.ytjj.qmyx.admin.dao.data.PlatformStatisticDao;
import com.ytjj.qmyx.admin.eunm.ActivityModuleEnums;
import com.ytjj.qmyx.admin.model.data.mongo.PageStatistics;
import com.ytjj.qmyx.admin.model.request.dataStatistics.DataStatisticsRequest;
import com.ytjj.qmyx.admin.model.response.DataResponse;
import com.ytjj.qmyx.admin.model.response.DataStatisticsResponse;
import com.ytjj.qmyx.admin.service.data.DataStatisticService;
import com.ytjj.qmyx.admin.utils.PathCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@RefreshScope
@Slf4j
@Service
public class DataStatisticServiceImpl implements DataStatisticService {

    @Resource
    private PlatformStatisticDao platformStatisticDao;

    @Resource
    private DataStatisticDao dataStatisticDao;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private RedisService redisService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private AnalysisDao analysisDao;

    @Value("${statistics.data}")
    private Boolean data;

    @Override
    public DataStatisticsResponse getAllChannelData(DataStatisticsRequest dataStatisticsRequest) {
        String time = LocalDate.now().toString();
        if(data && !time.equals(dataStatisticsRequest.getSearchDate())) {
            DataStatisticsResponse dataStatisticsResponse = new DataStatisticsResponse();
            List<DataResponse> channelData  = analysisDao.findDataInfo(dataStatisticsRequest.getPlatform(), dataStatisticsRequest.getChannel(), dataStatisticsRequest.getSearchDate());
            List<DataResponse> moduleChannelData  = analysisDao.findModuleDataList(dataStatisticsRequest.getSearchDate(),dataStatisticsRequest.getChannel());
            dataStatisticsResponse.setAllChannelDataList(channelData);
            dataStatisticsResponse.setModuleChannelDataList(moduleChannelData);
            return dataStatisticsResponse;
        }
        // 格式化时间后的请求
        return getResponse(dataStatisticsRequest);
    }

    private DataStatisticsResponse getResponse(DataStatisticsRequest dataStatisticsRequest) {
        this.getSearchDate(dataStatisticsRequest);
        DataStatisticsResponse dataStatisticsResponse = new DataStatisticsResponse();
        List<DataResponse> channelData = this.getChannelData(dataStatisticsRequest);
        ArrayList<DataResponse> moduleChannelData = this.getModuleChannelData(dataStatisticsRequest);
        dataStatisticsResponse.setAllChannelDataList(channelData);
        dataStatisticsResponse.setModuleChannelDataList(moduleChannelData);
        return dataStatisticsResponse;
    }

    private void saveResponse(DataStatisticsRequest request) {
        DataStatisticsResponse response = getResponse(request);
        analysisDao.saveDataList(response.getAllChannelDataList());
        analysisDao.saveDataModuleList(response.getModuleChannelDataList());
    }

    @Override
    public void timing () {
        LocalDate localDate = LocalDate.now().minusDays(1);
        log.info("----开始数据分析----------\n{}",localDate);
        Map channelMap = redisTemplate.opsForHash()
                .entries(StatisticsConstants.SKIP_NUM + localDate);

        analysisDao.delData(localDate);
        analysisDao.delDataModule(localDate);

        for (Object channelName : channelMap.keySet()) {
            String channel = channelName.toString();
            if ("all".equals(channel)){
                continue;
            }
            String platform = analysisDao.findPlatform(channel);
            DataStatisticsRequest request = new DataStatisticsRequest(platform, channel, localDate.toString(), 30L);
            saveResponse(request);
        }
        DataStatisticsRequest request = new DataStatisticsRequest("h5", null, localDate.toString(), 30L);
        saveResponse(request);
        DataStatisticsRequest request1 = new DataStatisticsRequest("android", null, localDate.toString(), 30L);
        saveResponse(request1);
        DataStatisticsRequest request2 = new DataStatisticsRequest("ios", null, localDate.toString(), 30L);
        saveResponse(request2);
        DataStatisticsRequest request3 = new DataStatisticsRequest("weapp", null, localDate.toString(), 30L);
        saveResponse(request3);

        redisTemplate.delete(StatisticsConstants.SKIP_NUM + localDate);
    }


    /**
     * 获取汇总渠道数据
     *
     * @param dataStatisticsRequest
     * @return
     */
    public List<DataResponse> getChannelData(DataStatisticsRequest dataStatisticsRequest) {
        LocalDateTime startTime = dataStatisticsRequest.getStartTime();
        LocalDateTime endTime = dataStatisticsRequest.getEndTime();
        String channel = dataStatisticsRequest.getChannel();
        String platform = dataStatisticsRequest.getPlatform();
        List<DataResponse> channelOrderDataList = new ArrayList<>();
        if(StringUtils.isNotEmpty(channel)) {
            List<String> channelList = this.getChannelList(channel);
            if(null !=data && data) {
                List<DataResponse> list = channelList.stream().map(channelItem -> this.channelDataNew(dataStatisticsRequest,dataStatisticsRequest.getSearchDate(), platform, channelItem)).collect(Collectors.toList());
                channelOrderDataList.addAll(list);
            }else {
                List<DataResponse> list = channelList.stream().map(channelItem -> this.channelData(dataStatisticsRequest,startTime, endTime, dataStatisticsRequest.getSearchDate(), platform, channelItem)).collect(Collectors.toList());
                channelOrderDataList.addAll(list);
            }
        } else {
            if(null !=data && data) {
                DataResponse channelOrderData = this.channelDataNew(dataStatisticsRequest,dataStatisticsRequest.getSearchDate(), platform, channel);
                channelOrderDataList.add(channelOrderData);
            } else {
                DataResponse channelOrderData = this.channelData(dataStatisticsRequest,startTime, endTime, dataStatisticsRequest.getSearchDate(), platform, channel);
                channelOrderDataList.add(channelOrderData);
            }
        }
        return channelOrderDataList;
    }


    /**
     * 获取模块渠道信息
     *
     * @param dataStatisticsRequest
     * @return
     */
    public ArrayList<DataResponse> getModuleChannelData(DataStatisticsRequest dataStatisticsRequest) {
        ArrayList<DataResponse> moduleDataList = new ArrayList<>();
        String searchDate = dataStatisticsRequest.getSearchDate();
        LocalDateTime startTime = dataStatisticsRequest.getStartTime();
        LocalDateTime endTime = dataStatisticsRequest.getEndTime();
        String channel = dataStatisticsRequest.getChannel();
        String platform = dataStatisticsRequest.getPlatform();
        // 模块订单信息
        ActivityModuleEnums[] activityModel = ActivityModuleEnums.values();

        if(null !=data && data) {
            Arrays.asList(activityModel).stream().forEach(item -> {
                if(StringUtils.isNotEmpty(channel)) {
                    List<String> channelList = this.getChannelList(channel);
                    List<DataResponse> list = channelList.parallelStream().map(channelItem -> this.moduleChannelDataNew(searchDate, platform, channelItem, item.getActivityCode())).collect(Collectors.toList());
                    moduleDataList.addAll(list);
                } else {
                    DataResponse channelOrderData = this.moduleChannelDataNew(searchDate, platform, channel, item.getActivityCode());
                    moduleDataList.add(channelOrderData);
                }
            });
        } else {
            Arrays.asList(activityModel).stream().forEach(item -> {
                if(StringUtils.isNotEmpty(channel)) {
                    List<String> channelList = this.getChannelList(channel);
                    List<DataResponse> list = channelList.parallelStream().map(channelItem -> this.moduleChannelData(startTime, endTime, searchDate, platform, channelItem, item.getActivityCode())).collect(Collectors.toList());
                    moduleDataList.addAll(list);
                } else {
                    DataResponse channelOrderData = this.moduleChannelData(startTime, endTime, searchDate, platform, channel, item.getActivityCode());
                    moduleDataList.add(channelOrderData);
                }
            });
        }
        return moduleDataList;
    }

    /**
     *  统计-数据分析统计
     *  汇总分析
     *
     * @param searchDate 统计日期
     * @param platform   平台
     * @param channel    渠道
     * @return
     */
    public DataResponse channelDataNew(DataStatisticsRequest request, String searchDate, String platform, String channel) {
        // 意向订单数
        Integer intentionOrderNum = getOrderNumber(searchDate, platform, channel, null, null, null);
        // 无地址订单数
        Integer noAddressOrderNum = getOrderNumber(searchDate, platform, channel, 0, null, null);
        // 支付订单数
        Integer payOrderNum = getOrderNumber(searchDate, platform, channel, null, 1, null);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
        // 转发数
        Integer transPondNum = getTransPondNum(platform,channel,searchDate);
        // 转发uv
        Integer transPondUv = getTransPondUv(channel,searchDate);

        DataResponse dateRes = getDateRes(searchDate, platform, channel, null, intentionOrderNum, noAddressOrderNum, payOrderNum, realOrderNum);


        // 意向订单数Uv
        Integer intentionOrderNumUv = getOrderUvNumber(searchDate, platform, channel, null, null, null, null);
        // 无地址订单数UV
        Integer noAddressOrderNumUv = getOrderUvNumber(searchDate, platform, channel, 0, null, null, null);
        // 支付订单数UV
        Integer payOrderNumUv= getOrderUvNumber(searchDate, platform, channel, null, 1, null, null);

        dateRes.setIntentionOrderNumUv(intentionOrderNumUv);
        dateRes.setNoAddressOrderNumUv(noAddressOrderNumUv);
        dateRes.setPayOrderNumUv(payOrderNumUv);
        dateRes.setTransPondNum(transPondNum);
        dateRes.setTransPondUv(transPondUv);
        return dateRes;
    }
    /**
     * 查询订单数据
     *
     * @param searchDate
     * @param platform
     * @param channel
     * @param isAddress
     * @param isPay
     * @param activityType
     * @param isFirstBuy
     * @return
     */
    public int getOrderUvNumber(String searchDate, String platform, String channel, Integer isAddress, Integer isPay, String activityType, Integer isFirstBuy) {
        Criteria criteria = Criteria.where("platform").is(platform);
        if(StringUtils.isNotEmpty(channel)) {
            criteria.and("channel").is(channel);
        }
        if(StringUtils.isNotEmpty(activityType)){
            criteria.and("activityType").is(activityType);
        }
        if(null != isAddress){
            criteria.and("isAddress").is(isAddress);
        }
        if(null != isPay){
            criteria.and("isPay").is(isPay);
        }
        if(null != isFirstBuy){
            criteria.and("isFirstBuy").is(isFirstBuy);
        }
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("uuid").count().as("count").last("dayTime").as("dayTime"),
                Aggregation.group("dayTime").count().as("count")
        );
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.ORDER + searchDate, Map.class);
        List<Map> maps = results.getMappedResults();
        if(maps.size() == 0){
            return 0;
        }
        Object count = maps.get(0).get("count");
        return Integer.parseInt(count.toString());
    }

    /**
     *  统计-数据分析统计
     *  模块分析
     *
     * @param searchDate 统计日期
     * @param platform   平台
     * @param channel    渠道
     * @return
     */
    public DataResponse moduleChannelDataNew(String searchDate, String platform, String channel, String activityCode) {
        // 意向订单数
        Integer intentionOrderNum = getOrderNumber(searchDate, platform, channel, null, null, activityCode);
        // 无地址订单数
        Integer noAddressOrderNum = getOrderNumber(searchDate, platform, channel, 0, null, activityCode);
        // 支付订单数
        Integer payOrderNum = getOrderNumber(searchDate, platform, channel, null, 1, activityCode);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
        List<String> pathCodeList=PathCodeUtil.getValue(activityCode);
        DataResponse dateRes = getDateRes(searchDate, platform, channel, pathCodeList, intentionOrderNum, noAddressOrderNum, payOrderNum, realOrderNum);
        dateRes.setActivityType(ActivityModuleEnums.getActivityType(activityCode));
        return dateRes;
    }


    public DataResponse getDateRes (String searchDate, String platform, String channel, List<String> pathCodeList,
                                    Integer intentionOrderNum, Integer noAddressOrderNum, Integer payOrderNum,Integer realOrderNum) {
        Long pv = this.getPv(searchDate, platform, channel, pathCodeList);
        Integer uv = this.getUvNew(searchDate, platform, channel, pathCodeList);
        // 订单率 实际订单数/uv
        BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : new BigDecimal(realOrderNum).divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP);
        // 支付率 （支付订单/实际订单数）
        BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : new BigDecimal(payOrderNum).divide(BigDecimal.valueOf(realOrderNum), 4, RoundingMode.HALF_UP);

        DataResponse dataResponse = new DataResponse();
        dataResponse.setChannel(channel);
        dataResponse.setPlatform(platform);
        dataResponse.setUv(uv);
        dataResponse.setPv(pv.intValue());
        dataResponse.setIntentionOrderNum(intentionOrderNum);
        dataResponse.setNoAddressOrderNum(noAddressOrderNum);
        dataResponse.setPayOrderNum(payOrderNum);
        dataResponse.setRecordTime(new Date());
        dataResponse.setOrderRatio(orderRatio);
        dataResponse.setPayRatio(payRatio);
        dataResponse.setRealOrderNum(realOrderNum);
        dataResponse.setTime(searchDate);
        return dataResponse;
    }


    /**
     * 获取页面统计uv
     *
     * @param searchDate
     * @param channel
     * @return
     */
    public Integer getUvNew(String searchDate, String platform, String channel,List<String> pathCodeList) {
        Criteria criteria = this.commonCriteria(platform, channel, searchDate, pathCodeList);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("uuid").count().as("count").last("dayTime").as("dayTime"),
                Aggregation.group("dayTime").count().as("count")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.PAGE + searchDate, Map.class);
        List<Map> maps = results.getMappedResults();
        if(maps.size() == 0) return 0;
        Object count = maps.get(0).get("count");
        return Integer.parseInt(count.toString());
    }

    /**
     *  获取转发数
     *
     * @param platform
     * @param channel
     * @param searchDate
     * @return
     */
    public Integer getTransPondNum(String platform, String channel,String searchDate) {
        if(PlatformConstant.PLATFORM_H5.equals(platform) || StringUtils.isNotEmpty(channel)) {
            try {
                Boolean all = redisTemplate.opsForHash().hasKey(StatisticsConstants.SKIP_NUM + searchDate, "all");
                if(all) {
                    if(StringUtils.isNotEmpty(channel)){
                        Object o = redisTemplate.opsForHash().get(StatisticsConstants.SKIP_NUM + searchDate, channel);
                        return o == null ? 0 : Integer.parseInt(o.toString());
                    } else {
                        Object o = redisTemplate.opsForHash().get(StatisticsConstants.SKIP_NUM + searchDate, "all");
                        return o == null ? 0 : Integer.parseInt(o.toString());
                    }
                } else {
                    Criteria criteria = Criteria.where("channel").is(channel);
                    return (int)mongoTemplate.count(Query.query(criteria), MongoCollectionNameConstants.SKIP + searchDate);
                }
            }catch (Exception e){}
        }
        return 0;
    }
    /**
     *  获取转发uv
     * @param channel
     * @param searchDate
     * @return
     */
    public Integer getTransPondUv(String channel,String searchDate) {
        Criteria criteria = this.commonCriteria(null, channel, searchDate, null);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("sessionid").count().as("count").last("dayTime").as("dayTime"),
                Aggregation.group("dayTime").count().as("count")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.SKIP + searchDate, Map.class);
        List<Map> maps = results.getMappedResults();
        if(maps.size() == 0){
            return 0;
        }
        Object count = maps.get(0).get("count");
        return Integer.parseInt(count.toString());
    }


    /**
     * 获取订单数据分析
     *
     * @param searchDate
     * @param platform
     * @param channel
     * @param isAddress
     * @param isPay
     * @param activityType
     * @return
     */
    public int getOrderNumber(String searchDate, String platform, String channel, Integer isAddress, Integer isPay, String activityType) {
        Criteria criteria = Criteria.where("platform").is(platform);
        if (StringUtils.isNotEmpty(channel)) {
            criteria.and("channel").is(channel);
        }
        if(StringUtils.isNotEmpty(activityType)) {
            criteria.and("activityType").is(activityType);
        }
        if(null != isAddress) {
            criteria.and("isAddress").is(isAddress);
        }
        if(null != isPay) {
            criteria.and("isPay").is(isPay);
        }
        long count = mongoTemplate.count(Query.query(criteria), MongoCollectionNameConstants.ORDER + searchDate);
        return (int) count;
    }

    /**
     *  汇总数据
     */
    public DataResponse channelData(DataStatisticsRequest request,LocalDateTime startTime, LocalDateTime endTime, String searchDate, String platform, String channel) {
        // 意向订单数
        Integer intentionOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, null, null);
        // 无地址订单数
        Integer noAddressOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, "1", null, null);
        // 支付订单数
        Integer payOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, null);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;
        // uv实际订单数
        Integer uvOrderNum = dataStatisticDao.getUvChannelOrderData(startTime, endTime, platform, channel, null, null, null);
        Integer uvNoAddressNum = dataStatisticDao.getUvChannelOrderData(startTime, endTime, platform, channel, "1", null, null);
        Integer uvRealOrderNum = uvOrderNum - uvNoAddressNum;
        Integer uvPayOrderNum = dataStatisticDao.getUvChannelOrderData(startTime, endTime, platform, channel, null, 1, null);
        // 转发数
        Integer transPondNum = 0;
        // 转发uv
        Integer transPondUv = 0;
        if(PlatformConstant.PLATFORM_H5.equals(platform) || StringUtils.isNotEmpty(channel)) {
            transPondNum = this.getTransPondNumNew(channel, searchDate);
            transPondUv = this.getTransPondUv(channel,searchDate);
        }
        // uv
        Integer uv = this.getUvNew(searchDate, platform, channel, null);
        // pv
        Long pv = this.getPv(searchDate, platform, channel, null);
        // 订单率 uv实际订单数/uv
        BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(uvRealOrderNum)
                .divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        // 支付率 （支付订单/实际订单）
        BigDecimal payRatio = realOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(uvPayOrderNum)
                .divide(BigDecimal.valueOf(uvRealOrderNum), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        DataResponse channelOrderData = new DataResponse();
        channelOrderData.setChannel(channel);
        channelOrderData.setPlatform(platform);
        channelOrderData.setUv(uv);
        channelOrderData.setPv(pv.intValue());
        channelOrderData.setIntentionOrderNum(intentionOrderNum);
        channelOrderData.setNoAddressOrderNum(noAddressOrderNum);
        channelOrderData.setPayOrderNum(payOrderNum);
        channelOrderData.setTransPondNum(transPondNum);
        channelOrderData.setTransPondUv(transPondUv);
        channelOrderData.setRealOrderNum(realOrderNum);
        channelOrderData.setPayRatio(payRatio);
        channelOrderData.setRecordTime(new Date());
        channelOrderData.setOrderRatio(orderRatio);
        channelOrderData.setTime(platform+searchDate);

        channelOrderData.setIntentionOrderNumUv(uvOrderNum);
        channelOrderData.setNoAddressOrderNumUv(uvNoAddressNum);
        channelOrderData.setPayOrderNumUv(uvPayOrderNum);
        return channelOrderData;
    }


    /**
     * 模块数据
     */
    public DataResponse moduleChannelData(LocalDateTime startTime, LocalDateTime endTime, String searchDate, String platform, String channel, String activityCode) {
        // 意向订单数
        Integer intentionOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, null, activityCode);
        // 无地址订单数
        Integer noAddressOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, "1", null, activityCode);
        // 支付订单数
        Integer payOrderNum = dataStatisticDao.getChannelOrderData(startTime, endTime, platform, channel, null, 1, activityCode);
        // 实际订单数
        Integer realOrderNum = intentionOrderNum - noAddressOrderNum;

        Integer uvOrderNum = dataStatisticDao.getUvChannelOrderData(startTime, endTime, platform, channel, null, null, activityCode);
        Integer uvNoAddressNum = dataStatisticDao.getUvChannelOrderData(startTime, endTime, platform, channel, "1", null, activityCode);
        Integer uvRealOrderNum = uvOrderNum - uvNoAddressNum;
        Integer uvPayOrderNum = dataStatisticDao.getUvChannelOrderData(startTime, endTime, platform, channel, null, 1, activityCode);

        List<String> pathCodeList=PathCodeUtil.getValue(activityCode);
        Integer uv = this.getUvNew(searchDate, platform, channel, pathCodeList);
        // 订单率 实际订单数/uv
        BigDecimal orderRatio = uv == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(uvRealOrderNum)
                .divide(BigDecimal.valueOf(uv), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        // 支付率 （支付订单/实际订单数）
        BigDecimal payRatio = uvRealOrderNum == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(uvPayOrderNum)
                .divide(BigDecimal.valueOf(uvRealOrderNum), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
        DataResponse channelOrderData = new DataResponse();
        channelOrderData.setChannel(channel);
        channelOrderData.setPlatform(platform);
        channelOrderData.setUv(uv);
        channelOrderData.setIntentionOrderNum(intentionOrderNum);
        channelOrderData.setNoAddressOrderNum(noAddressOrderNum);
        channelOrderData.setIntentionOrderNumUv(uvOrderNum);
        channelOrderData.setNoAddressOrderNumUv(uvNoAddressNum);
        channelOrderData.setPayOrderNumUv(uvPayOrderNum);
        channelOrderData.setPayOrderNum(payOrderNum);
        channelOrderData.setPayRatio(payRatio);
        channelOrderData.setRealOrderNum(realOrderNum);
        channelOrderData.setOrderRatio(orderRatio);
        channelOrderData.setActivityType(ActivityModuleEnums.getActivityType(activityCode));
        channelOrderData.setRecordTime(new Date());
        channelOrderData.setTime(platform+searchDate);
        return channelOrderData;
    }


    /**
     * 是否有子类
     */
    public List<String> getChannelList(String channel) {
        List<String> channelList = new ArrayList<>();
        channelList.add(channel);
        List<String> strings = dataStatisticDao.childListByChannel(channel);
        if(null != strings) channelList.addAll(strings);
        return channelList;
    }


    /**
     * 获取uv
     *
     * @param searchDate
     * @param channel
     * @param pathCodeList
     * @return
     */
    public Integer getUv(String searchDate, String platform, String channel, List<String> pathCodeList) {
        Criteria criteria = this.commonCriteria(platform, channel, searchDate, pathCodeList);
        Integer integer = Optional.ofNullable(this.aggregateByUuid(criteria).size()).orElse(0);
        return integer;
    }

    /**
     * 获取pv
     *
     * @param searchDate
     * @param channel
     * @param pathCodeList
     * @return
     */
    public Long getPv(String searchDate, String platform, String channel,List<String> pathCodeList) {
        Criteria criteria = this.commonCriteria(platform, channel, searchDate, pathCodeList);
        return Optional.ofNullable(mongoTemplate.count(new Query(criteria), PageStatistics.class)).orElse(Long.valueOf(0));
    }


    /**
     * 获取转发数
     *
     * @param channel
     * @param searchTime
     * @return
     */
    public Integer getTransPondNum(String channel, String searchTime) {
        Criteria criteria = this.commonCriteria(null, channel, searchTime, null);
        Integer integer = Optional.ofNullable(this.aggregateBySessionid(criteria).size()).orElse(0);
        return integer;
    }

    /**
     * 获取转发数
     *
     * @param searchDate
     * @param channel
     * @return
     */
    public Integer getTransPondNumNew(String channel, String searchDate) {
        Criteria criteria = new Criteria();
        if(StringUtils.isNotEmpty(channel)){
            criteria.and("channel").is(channel);
        }
//        Aggregation aggregation = Aggregation.newAggregation(
//                Aggregation.match(criteria),
//                Aggregation.group("sessionid"),
//                Aggregation.count().as("sessionCount")
//        );
//        Map map=mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.SKIP + searchDate, Map.class).getUniqueMappedResult();
//        return null == map ? 0 : (Integer) map.get("sessionCount");
        return (int) mongoTemplate.count(Query.query(criteria), MongoCollectionNameConstants.SKIP + searchDate);
    }


    /**
     * 通用查询
     *
     * @param channel
     * @return
     */
    public Criteria commonCriteria(String platform, String channel, String searchDate,List<String> pathCodeList) {
        Criteria criteria = Criteria.where("dayTime").is(searchDate);
        if (StringUtils.isNotEmpty(channel)) {
            criteria.and("channel").is(channel);
        }
        if (StringUtils.isNotEmpty(platform)) {
            criteria.and("platform").is(platform);
        }
        if(pathCodeList!=null&&pathCodeList.size()>0) {
            criteria.and("pathCode").in(pathCodeList);
        }
        return criteria;
    }


    public List<Map> aggregateByUuid(Criteria criteria) {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("uuid").count().as("count").last("uuid").as("uuid")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.PAGE_STATISTICS, Map.class);
        return results.getMappedResults();
    }


    public List<Map> aggregateBySessionid(Criteria criteria) {
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("sessionid").count().as("count").last("sessionid").as("sessionid")
        ).withOptions(AggregationOptions.builder().allowDiskUse(true).build());
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, MongoCollectionNameConstants.SKIP_STATISTICS , Map.class);
        return results.getMappedResults();
    }





    /**
     * 查询时间格式化
     * @param dataStatisticsRequest
     * @return
     */
    public void getSearchDate(DataStatisticsRequest dataStatisticsRequest) {
        if(Strings.isNotEmpty(dataStatisticsRequest.getSearchDate())) {
            LocalDate day = LocalDate.parse(dataStatisticsRequest.getSearchDate());
            LocalDateTime startTime = day.atStartOfDay();
            LocalDateTime endTime = startTime.plusDays(1);
            dataStatisticsRequest.setStartTime(startTime);
            dataStatisticsRequest.setEndTime(endTime);
        }
    }




}
